package com.hst.capacity.application.biz.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.smartravel.map.baidu.RouteMatrix;
import cn.smartravel.traffic.alitrip.AlitripCarOpen;
import cn.smartravel.traffic.usoft17.RideSupplierCallback;
import cn.smartravel.traffic.usoft17.model.request.callback.OrderStatusDTO;
import cn.smartravel.traffic.usoft17.model.response.callback.ResultVO;
import com.alibaba.fastjson2.JSON;
import com.hst.capacity.application.biz.IntercityOrderBiz;
import com.hst.capacity.application.biz.JobPlatformBiz;
import com.hst.capacity.domain.common.constants.AliTripTransferConstants;
import com.hst.capacity.domain.common.constants.Constants;
import com.hst.capacity.domain.common.constants.MessageTemplate;
import com.hst.capacity.domain.common.constants.TongChengConstants;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.account.IcDriverAccountDetailEntity;
import com.hst.capacity.domain.model.entity.driver.DriverEntity;
import com.hst.capacity.domain.model.entity.member.MemberEntity;
import com.hst.capacity.domain.model.entity.order.express.ExpressOrderEntity;
import com.hst.capacity.domain.model.entity.order.intercity.*;
import com.hst.capacity.domain.model.entity.order.job.JobPlatformEntity;
import com.hst.capacity.domain.model.entity.order.pool.OrderPoolEntity;
import com.hst.capacity.domain.model.entity.setting.line.CityLineEntity;
import com.hst.capacity.domain.model.entity.setting.line.IntercityLineEntity;
import com.hst.capacity.domain.model.entity.setting.price.IntercityPriceEntity;
import com.hst.capacity.domain.model.entity.setting.price.IntercityStpPriceEntity;
import com.hst.capacity.domain.model.entity.setting.station.ApplyStationEntity;
import com.hst.capacity.domain.model.entity.setting.station.StationEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleEntity;
import com.hst.capacity.domain.model.request.OrderParam;
import com.hst.capacity.domain.model.request.dispatch.DispatchDriverParam;
import com.hst.capacity.domain.model.request.dispatch.DispatchParam;
import com.hst.capacity.domain.model.request.dispatcher.DispatcherSearchOrderParam;
import com.hst.capacity.domain.model.request.intercity.*;
import com.hst.capacity.domain.model.request.price.IntercityPriceParam;
import com.hst.capacity.domain.model.request.price.IntercityRePriceParam;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.model.response.dispatch.CityLineVO;
import com.hst.capacity.domain.model.response.driver.DriverInfoVO;
import com.hst.capacity.domain.model.response.intercity.*;
import com.hst.capacity.domain.model.response.intercity.task.IcSearchTaskVO;
import com.hst.capacity.domain.model.response.intercity.task.IcTaskDetailVO;
import com.hst.capacity.domain.model.response.order.IcOrderInfoVO;
import com.hst.capacity.domain.model.response.order.OrderPriceVO;
import com.hst.capacity.domain.model.response.order.OrderVO;
import com.hst.capacity.domain.model.response.setting.RouteVO;
import com.hst.capacity.domain.model.response.setting.line.CustomCityLineVO;
import com.hst.capacity.domain.repository.redis.CacheRedis;
import com.hst.capacity.domain.repository.redis.RouteRedis;
import com.hst.capacity.domain.service.*;
import com.hst.capacity.infra.convertor.*;
import com.hst.capacity.infra.persistence.jpa.account.IcDriverAccountDetailRepository;
import com.hst.capacity.infra.persistence.jpa.driver.DriverProfileRepository;
import com.hst.capacity.infra.persistence.jpa.driver.DriverRepository;
import com.hst.capacity.infra.persistence.jpa.order.express.ExOrderHistoryRepository;
import com.hst.capacity.infra.persistence.jpa.order.intercity.*;
import com.hst.capacity.infra.persistence.jpa.order.job.JobPlatformRepository;
import com.hst.capacity.infra.persistence.jpa.setting.line.CityLineRepository;
import com.hst.capacity.infra.persistence.jpa.setting.line.IntercityLineRepository;
import com.hst.capacity.infra.persistence.jpa.setting.price.IcPriceRepository;
import com.hst.capacity.infra.persistence.jpa.setting.price.IcStpPriceRepository;
import com.hst.capacity.infra.persistence.jpa.setting.station.ApplyStationRepository;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleRepository;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleTypeRepository;
import com.hst.capacity.infra.persistence.mybatis.IntercityOrderMapper;
import com.hst.capacity.infra.util.DateUtil;
import com.hst.capacity.infra.util.NumUtil;
import com.hst.capacity.infra.util.StringUtil;
import com.taobao.api.request.AlitripCarOrderConfirmRequest;
import com.taobao.api.response.AlitripCarOrderConfirmResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class IntercityOrderBizImpl implements IntercityOrderBiz {

    @Autowired
    IcOrderRepository orderRepository;
    @Autowired
    IcOrderHistoryRepository orderHistoryRepository;
    @Autowired
    IcOrderSettlementRepository orderSettlementRepository;
    @Autowired
    IcDriverAccountDetailRepository accountDetailRepository;
    @Autowired
    IcPriceRepository icPriceRepository;
    @Autowired
    IcOrderDispatchRepository icDispatchRepository;
    @Autowired
    IntercityService intercityService;
    @Autowired
    RouteMatrix routeMatrix;
    @Autowired
    IntercityLineRepository lineRepository;
    @Autowired
    CityLineRepository cityLineRepository;
    @Autowired
    MemberService memberService;
    @Autowired
    IntercityOrderMapper orderMapper;
    @Autowired
    IcOrderDestroyRepository destroyRepository;
    @Autowired
    DriverRepository driverRepository;
    @Autowired
    DriverProfileRepository driverProfileRepository;
    @Autowired
    DriverService driverService;
    @Autowired
    VehicleService vehicleService;
//    @Autowired
//    IntercityDriverTaskRepository icDriverTaskRepository;
    @Autowired
    JobPlatformRepository jobRepository;
    @Autowired
    VehicleTypeRepository vehicleTypeRepository;
    @Autowired
    IcOrderOperationHistoryRepository icOrderOperationHistoryRepository;
    @Autowired
    IcOrderStatusHistoryRepository orderStatusHistoryRepository;
    @Autowired
    IcOrderCancelHistoryRepository orderCancelHistoryRepository;
    @Autowired
    VehicleRepository vehicleRepository;
    @Autowired
    JobPlatformBiz jobPlatformBiz;
    @Autowired
    IcOrderResultRepository icOrderResultRepository;
    @Autowired
    IcStpPriceRepository icStpPriceRepository;
    @Autowired
    ApplyStationRepository applyStationRepository;
//    @Autowired
//    WeMapTemplate weMapTemplate;
    @Autowired
    RouteRedis routeRedis;
    @Autowired
    RideSupplierCallback callback;
    @Autowired
    AlitripCarOpen alitripCarOpen;

    @Autowired
    AuthService authService;
    @Autowired
    CacheRedis cacheRedis;

    @Override
    public OrderVO refresh(OrderParam param) {
        IntercityOrderEntity order = orderRepository.findByIdOrder(param.getIdOrder());
        return OrderConvertor.INSTANCE.icOrderToView(order);
    }

    /**
     * 创建城际订单
     * @param param
     * @return
     */
    @Override
    public IntercityOrderEntity saveIntercityOrder(IntercityCreateOrderParam param) {
        //1，乘客账户存在时，前端未传值的情况下，取得乘客信息放到对应参数当中
        MemberEntity member = memberService.createNewMember(param.getUserMobile());

        //定价ID未知时，取得并保存
        IntercityPriceParam price = new IntercityPriceParam();
        StringBuffer origins = new StringBuffer(param.getStartAddressLatitude()).append(",").append(param.getStartAddressLongitude());
        StringBuffer dest = new StringBuffer(param.getEndAddressLatitude()).append(",").append(param.getEndAddressLongitude());
        price.setIdLine(param.getIdLine());
        price.setOrigins(origins.toString());
        price.setDestinations(dest.toString());
        price.setPassengerNumber(param.getPassengerNumber());
        price.setCarpoolType(param.getCarpoolType());
        price.setIdStation(param.getIdStation());
        OrderPriceVO oprv = calIntercityPrice(price);
        //保存订单信息
//        IntercityOrderEntity entity = Convert.convert(IntercityOrderEntity.class, param);
        IntercityOrderEntity entity = null;
        boolean isCreate = true;
        if (StringUtil.isBlank(param.getIdOrder())){
            entity = new IntercityOrderEntity();
            entity.setIdOrder(StringUtil.createOrderID(1));
            entity.setCreateBy("capacity");
        }else{
            entity = orderRepository.findById(param.getIdOrder()).get();
            if (entity == null)
                throw new BusinessException(5002,"订单不存在，请检查参数idOrder是否正确");
            isCreate = false;
            entity.setIdOrder(param.getIdOrder());
            entity.setUpdateBy("capacity");
        }

        entity.setIdTask(param.getIdTask());
        entity.setIdLine(param.getIdLine());
        entity.setAdditionalMoney(param.getAdditionalMoney());
        entity.setStatus(param.getStatus());
        entity.setIsContact(param.getIsContact());

        entity.setIdMember(member.getIdMember());
        entity.setIdCorporate(param.getIdCorporate());
        entity.setCorporateName(param.getCorporateName());
        entity.setIdDriver(param.getIdDriver());
        entity.setIdFranchisee(param.getIdFranchisee());
        entity.setFullName(param.getFullName());
        entity.setCarpoolType(param.getCarpoolType());
        entity.setIdServiceType(Constants.Service_Type.get(entity.getCarpoolType()));// 数据库默认99
        entity.setIdVehicleType(param.getIdVehicleType());
        entity.setModel(param.getModel());
//        String id_service_price_type = StringUtil.isBlank(param.getIdServicePriceType()) ? param.getIdServicePriceType() : oprv.getIdServicePriceType();
        entity.setIdServicePriceType(oprv.getIdServicePriceType());
        entity.setOrderType(param.getOrderType());// 订单类型无效
        entity.setIdRelationshipOrder(param.getIdRelationshipOrder());
        entity.setDriverSubsidy(param.getDriverSubsidy());
        entity.setDriverNoLoadSubsidy(param.getDriverNoLoadSubsidy());
        entity.setUserName(param.getUserMobile());
        entity.setUserMobile(param.getUserMobile());
        entity.setPassengerName(param.getUserName());//传值下单用户名
        entity.setPassengerMobile(param.getPassengerMobile());
        entity.setPassengerNumber(param.getPassengerNumber());
        entity.setPlateNumber(param.getPlateNumber());
        entity.setVehicleInfo(param.getVehicleInfo());
        entity.setAppointmentTime(DateUtil.parseLocalDateTime(param.getAppointmentTime()));
        entity.setCutOffTime(DateUtil.parseLocalDateTime(param.getCutOffTime()));
        entity.setAssignTime(DateUtil.parseLocalDateTime(param.getAssignTime()));
        entity.setDriverLongitude(param.getDriverLongitude());
        entity.setDriverLatitude(param.getDriverLatitude());
        entity.setDeptime(DateUtil.parseLocalDateTime(param.getDeptime()));
        entity.setStartAddress(param.getStartAddress());
        entity.setStartAddressLongitude(param.getStartAddressLongitude());
        entity.setStartAddressLatitude(param.getStartAddressLatitude());
        entity.setEndAddress(param.getEndAddress());
        entity.setEndAddressLongitude(param.getEndAddressLongitude());
        entity.setEndAddressLatitude(param.getEndAddressLatitude());
        entity.setDropOffArea(param.getDropOffArea());
        entity.setDropOffAreaLongitude(param.getDropOffAreaLongitude());
        entity.setDropOffAreaLatitude(param.getDropOffAreaLatitude());
        entity.setDesttime(DateUtil.parseLocalDateTime(param.getDesttime()));
        entity.setStartServiceTime(DateUtil.parseLocalDateTime(param.getStartServiceTime()));
        entity.setEndServiceTime(DateUtil.parseLocalDateTime(param.getEndServiceTime()));
        entity.setIdStation(param.getIdStation());
        entity.setReferenceDistance(oprv.getOrderDistance());//预估花费距离
        entity.setEstimatedTime(oprv.getSpendTime());//预估花费时间
        entity.setEstimatedMoney(oprv.getTotalPrice());//预估花费金额
        entity.setGpsPn(param.getGpsPn());
        entity.setPayMoney(param.getPayMoney());
        entity.setCouponCode(param.getCouponCode());
        entity.setCouponDiscount(param.getCouponDiscount());
        entity.setOrderSource(param.getOrderSource());
        entity.setPaymentType(param.getPaymentType());
        int paymentStatus = (param.getPaymentStatus() == null) ? Constants.PaymentStatus.UN_PAY : param.getPaymentStatus();
        entity.setPaymentStatus(paymentStatus);
        int paymentRequitment = (param.getPaymentRequitment() == null) ? Constants.PaymentRequitment.IN_ADVANCE : param.getPaymentRequitment();
        entity.setPaymentRequitment(paymentRequitment);
        entity.setTranFlag(param.getTranFlag());
        entity.setPassengerConfirmArrival(param.getPassengerConfirmArrival());//
        int status = Constants.OrderStatus.ORDER_STATUS_CREATED;
        if (param.getStatus() != null)
            status = param.getStatus();
        entity.setStatus(status);
        entity.setDivideAccountsStatus(param.getDivideAccountsStatus());
        entity.setOrderMemo(param.getOrderMemo());
        entity.setDriverMemo(param.getDriverMemo());
        entity.setPassengerMemo(param.getPassengerMemo());
        entity.setCreateBy("capacity");
        entity = orderRepository.save(entity);

        if (isCreate) {
            //追加订单状态
            IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
            orderStatus.setIdOrder(entity.getIdOrder());
            orderStatus.setStatus(entity.getStatus());
            orderStatus.setCreateBy("capacity");
            orderStatus.setMemo("运力商系统录入订单");
            orderStatusHistoryRepository.save(orderStatus);
        } else {
            //修改记录

        }

        //订单结果(未完成)
        //判断一口价生成账单
        IntercityOrderResultEntity resultEntity = icOrderResultRepository.findByIdOrder(entity.getIdOrder());
        if (resultEntity == null)
            resultEntity = OrderConvertor.INSTANCE.icOrderReslutConvert(param);

        resultEntity.setIdOrder(entity.getIdOrder());
        resultEntity.setOrderDistance(oprv.getOrderDistance());
        resultEntity.setOrderReferenceDistance(oprv.getOrderDistance());
        resultEntity.setOrderSpendTime(oprv.getSpendTime());
        resultEntity.setIdServicePriceSetting(oprv.getIdServicePriceType());
        resultEntity.setOrderBasePrice(oprv.getBasePrice());
        resultEntity.setOrderPerKilometres(oprv.getPerKilometres());
        resultEntity.setOrderPerTime(oprv.getPerTime());
        resultEntity.setOverMileMoney(oprv.getOverMileMoney());
        resultEntity.setOverTimeMoney(oprv.getOverTimeMoney());
        resultEntity.setBaseTotalMoney(oprv.getTotalPrice());
        icOrderResultRepository.save(resultEntity);


        return entity;
    }

    /**
     * 创建城际订单
     * @param param
     * @return
     */
    @Override
    public IntercityOrderEntity createIntercityOrder(IntercityCreateOrderParam param) {
        //1，乘客账户存在时，前端未传值的情况下，取得乘客信息放到对应参数当中
        MemberEntity member = memberService.createNewMember(param.getUserMobile());

        //定价ID未知时，取得并保存
        IntercityPriceParam price = new IntercityPriceParam();
        StringBuffer origins = new StringBuffer(param.getStartAddressLatitude()).append(",").append(param.getStartAddressLongitude());
        StringBuffer dest = new StringBuffer(param.getEndAddressLatitude()).append(",").append(param.getEndAddressLongitude());
        price.setIdLine(param.getIdLine());
        price.setOrigins(origins.toString());
        price.setDestinations(dest.toString());
        price.setPassengerNumber(param.getPassengerNumber());
        price.setCarpoolType(param.getCarpoolType());
        price.setIdStation(param.getIdStation());
        OrderPriceVO oprv = calIntercityPrice(price);
        //保存订单信息
//        IntercityOrderEntity entity = Convert.convert(IntercityOrderEntity.class, param);
        IntercityOrderEntity entity = new IntercityOrderEntity();
        if (StringUtil.empty2Null(param.getIdOrder())==null){
            entity.setIdOrder(StringUtil.createOrderID(1));
            entity.setIdTask(param.getIdTask());
            entity.setStatus(param.getStatus());

            entity.setIdDriver(param.getIdDriver());
            entity.setIdFranchisee(param.getIdFranchisee());
            int paymentStatus = (param.getPaymentStatus() == null) ? Constants.PaymentStatus.UN_PAY : param.getPaymentStatus();
            entity.setPaymentStatus(paymentStatus);
            int paymentRequitment = (param.getPaymentRequitment() == null) ? Constants.PaymentRequitment.IN_ADVANCE : param.getPaymentRequitment();
            entity.setPaymentRequitment(paymentRequitment);
            entity.setTranFlag(param.getTranFlag());
            entity.setPassengerConfirmArrival(param.getPassengerConfirmArrival());//
            entity.setStatus(Constants.OrderStatus.ORDER_STATUS_CREATED);
            entity.setDivideAccountsStatus(param.getDivideAccountsStatus());

            entity.setCreateBy("capacity");
        }else{
            entity = orderRepository.findByIdOrder(param.getIdOrder());
            entity.setUpdateBy("capacity");
        }

        entity.setIdLine(param.getIdLine());
        entity.setAdditionalMoney(param.getAdditionalMoney());

        entity.setIsContact(param.getIsContact());

        entity.setIdMember(member.getIdMember());
        entity.setIdCorporate(param.getIdCorporate());
        entity.setCorporateName(param.getCorporateName());
        entity.setFullName(param.getFullName());

        entity.setCarpoolType(param.getCarpoolType());
        entity.setIdServiceType(Constants.Service_Type.get(entity.getCarpoolType()));// 数据库默认99
        entity.setIdVehicleType(param.getIdVehicleType());
        entity.setModel(param.getModel());
//        String id_service_price_type = StringUtil.isBlank(param.getIdServicePriceType()) ? param.getIdServicePriceType() : oprv.getIdServicePriceType();
        entity.setIdServicePriceType(oprv.getIdServicePriceType());
        entity.setOrderType(param.getOrderType());// 订单类型无效
        entity.setIdRelationshipOrder(param.getIdRelationshipOrder());
        entity.setDriverSubsidy(param.getDriverSubsidy());
        entity.setDriverNoLoadSubsidy(param.getDriverNoLoadSubsidy());
        entity.setUserName(param.getUserMobile());
        entity.setUserMobile(param.getUserMobile());
        entity.setPassengerName(param.getUserName());//传值下单用户名
        entity.setPassengerMobile(param.getPassengerMobile());
        entity.setPassengerNumber(param.getPassengerNumber());
        entity.setPlateNumber(param.getPlateNumber());
        entity.setVehicleInfo(param.getVehicleInfo());
        entity.setAppointmentTime(DateUtil.parseLocalDateTime(param.getAppointmentTime()));
        entity.setCutOffTime(DateUtil.parseLocalDateTime(param.getCutOffTime()));
        entity.setAssignTime(DateUtil.parseLocalDateTime(param.getAssignTime()));
        entity.setDriverLongitude(param.getDriverLongitude());
        entity.setDriverLatitude(param.getDriverLatitude());
        entity.setDeptime(DateUtil.parseLocalDateTime(param.getDeptime()));
        entity.setStartAddress(param.getStartAddress());
        entity.setStartAddressLongitude(param.getStartAddressLongitude());
        entity.setStartAddressLatitude(param.getStartAddressLatitude());
        entity.setEndAddress(param.getEndAddress());
        entity.setEndAddressLongitude(param.getEndAddressLongitude());
        entity.setEndAddressLatitude(param.getEndAddressLatitude());
        entity.setDropOffArea(param.getDropOffArea());
        entity.setDropOffAreaLongitude(param.getDropOffAreaLongitude());
        entity.setDropOffAreaLatitude(param.getDropOffAreaLatitude());
        entity.setDesttime(DateUtil.parseLocalDateTime(param.getDesttime()));
        entity.setStartServiceTime(DateUtil.parseLocalDateTime(param.getStartServiceTime()));
        entity.setEndServiceTime(DateUtil.parseLocalDateTime(param.getEndServiceTime()));
        entity.setIdStation(param.getIdStation());
        entity.setReferenceDistance(oprv.getOrderDistance());//预估花费距离
        entity.setEstimatedTime(oprv.getSpendTime());//预估花费时间
        entity.setEstimatedMoney(oprv.getTotalPrice());//预估花费金额
        //entity.setGpsPn(param.getGpsPn());
        //entity.setPayMoney(param.getPayMoney());
        //entity.setCouponCode(param.getCouponCode());
        //entity.setCouponDiscount(param.getCouponDiscount());
        entity.setOrderSource(param.getOrderSource());
        //entity.setPaymentType(param.getPaymentType());

        entity.setOrderMemo(param.getOrderMemo());
        //entity.setDriverMemo(param.getDriverMemo());
        //entity.setPassengerMemo(param.getPassengerMemo());

        entity.setSubBizType(param.getSubBizType());

        IntercityOrderEntity returnEntity = orderRepository.save(entity);

        //追加订单状态
        IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
        orderStatus.setIdOrder(entity.getIdOrder());
        orderStatus.setStatus(entity.getStatus());
        orderStatus.setCreateBy("capacity");
        orderStatus.setMemo("运力商系统录入订单");
        orderStatusHistoryRepository.save(orderStatus);

        //订单结果(未完成)
        //判断一口价生成账单
        IntercityOrderResultEntity resultEntity = icOrderResultRepository.findByIdOrder(entity.getIdOrder());
        if (resultEntity == null)
            resultEntity = OrderConvertor.INSTANCE.icOrderReslutConvert(param);

        resultEntity.setIdOrder(entity.getIdOrder());
        resultEntity.setOrderDistance(oprv.getOrderDistance());
        resultEntity.setOrderReferenceDistance(oprv.getOrderDistance());
        resultEntity.setOrderSpendTime(oprv.getSpendTime());
        resultEntity.setIdServicePriceSetting(oprv.getIdServicePriceType());
        resultEntity.setOrderBasePrice(oprv.getBasePrice());
        resultEntity.setOrderPerKilometres(oprv.getPerKilometres());
        resultEntity.setOrderPerTime(oprv.getPerTime());
        resultEntity.setOverMileMoney(oprv.getOverMileMoney());
        resultEntity.setOverTimeMoney(oprv.getOverTimeMoney());
        resultEntity.setBaseTotalMoney(oprv.getTotalPrice());
        icOrderResultRepository.save(resultEntity);

        return returnEntity;
    }

    /**
     * 创建城际订单
     * @param param
     * @return
     */
    @Override
    public IntercityOrderEntity createOrder(IntercityCreateOrderParam param) {
        //1，乘客账户存在时，前端未传值的情况下，取得乘客信息放到对应参数当中
        MemberEntity member = memberService.createNewMember(param.getUserMobile());

        OrderPriceVO oprv = null;
        //定价ID未知时，取得并保存
        IntercityPriceParam icPriceParam = new IntercityPriceParam();
        StringBuffer origins = new StringBuffer(param.getStartAddressLatitude()).append(",").append(param.getStartAddressLongitude());
        StringBuffer dest = new StringBuffer(param.getEndAddressLatitude()).append(",").append(param.getEndAddressLongitude());
        icPriceParam.setIdLine(param.getIdLine());
        icPriceParam.setOrigins(origins.toString());
        icPriceParam.setDestinations(dest.toString());
        icPriceParam.setPassengerNumber(param.getPassengerNumber());
        icPriceParam.setCarpoolType(param.getCarpoolType());
        icPriceParam.setIdStation(param.getIdStation());
        if (StringUtil.isNotBlank(param.getIdFranchisee()))
            icPriceParam.setIdFranchisee(param.getIdFranchisee());

        //OrderPriceVO vo = new OrderPriceVO();
        if (Constants.ExSubBizType.InnerCity == param.getSubBizType()) {
            oprv = this.getIntercityPrice(icPriceParam);
        }
        if (Constants.ExSubBizType.StationToStation == param.getSubBizType()) {
            icPriceParam.setIdStation(param.getIdStation());
            oprv = this.getCommonPrice(icPriceParam);
        }

        //保存订单信息
//        IntercityOrderEntity entity = Convert.convert(IntercityOrderEntity.class, param);
        IntercityOrderEntity entity = new IntercityOrderEntity();
        if (StringUtil.empty2Null(param.getIdOrder())==null){
            entity.setIdOrder(StringUtil.createOrderID(1));
            entity.setIdTask(param.getIdTask());
            entity.setStatus(param.getStatus());

            entity.setIdDriver(param.getIdDriver());
            entity.setIdFranchisee(param.getIdFranchisee());
            int paymentStatus = (param.getPaymentStatus() == null) ? Constants.PaymentStatus.UN_PAY : param.getPaymentStatus();
            entity.setPaymentStatus(paymentStatus);
            int paymentRequitment = (param.getPaymentRequitment() == null) ? Constants.PaymentRequitment.IN_ADVANCE : param.getPaymentRequitment();
            entity.setPaymentRequitment(paymentRequitment);
            entity.setTranFlag(param.getTranFlag());
            entity.setPassengerConfirmArrival(param.getPassengerConfirmArrival());//
            entity.setStatus(Constants.OrderStatus.ORDER_STATUS_CREATED);
            entity.setDivideAccountsStatus(param.getDivideAccountsStatus());

            entity.setCreateBy("capacity");
        }else{
            entity = orderRepository.findByIdOrder(param.getIdOrder());
            entity.setUpdateBy("capacity");
        }

        entity.setIdLine(param.getIdLine());
        entity.setAdditionalMoney(param.getAdditionalMoney());

        entity.setIsContact(param.getIsContact());

        entity.setIdMember(member.getIdMember());
        entity.setIdCorporate(param.getIdCorporate());
        entity.setCorporateName(param.getCorporateName());
        entity.setFullName(param.getFullName());

        entity.setCarpoolType(param.getCarpoolType());
        entity.setIdServiceType(Constants.Service_Type.get(entity.getCarpoolType()));// 数据库默认99
        entity.setIdVehicleType(param.getIdVehicleType());
        entity.setModel(param.getModel());
//        String id_service_price_type = StringUtil.isBlank(param.getIdServicePriceType()) ? param.getIdServicePriceType() : oprv.getIdServicePriceType();
        entity.setIdServicePriceType(oprv.getIdServicePriceType());
        entity.setOrderType(param.getOrderType());// 订单类型无效
        entity.setIdRelationshipOrder(param.getIdRelationshipOrder());
        entity.setDriverSubsidy(param.getDriverSubsidy());
        entity.setDriverNoLoadSubsidy(param.getDriverNoLoadSubsidy());
        entity.setUserName(param.getUserMobile());
        entity.setUserMobile(param.getUserMobile());
        entity.setPassengerName(param.getUserName());//传值下单用户名
        entity.setPassengerMobile(param.getPassengerMobile());
        entity.setPassengerNumber(param.getPassengerNumber());
        entity.setPlateNumber(param.getPlateNumber());
        entity.setVehicleInfo(param.getVehicleInfo());
        entity.setAppointmentTime(DateUtil.parseLocalDateTime(param.getAppointmentTime()));
        entity.setCutOffTime(DateUtil.parseLocalDateTime(param.getCutOffTime()));
        entity.setAssignTime(DateUtil.parseLocalDateTime(param.getAssignTime()));
        entity.setDriverLongitude(param.getDriverLongitude());
        entity.setDriverLatitude(param.getDriverLatitude());
        entity.setDeptime(DateUtil.parseLocalDateTime(param.getDeptime()));
        entity.setStartAddress(param.getStartAddress());
        entity.setStartAddressLongitude(param.getStartAddressLongitude());
        entity.setStartAddressLatitude(param.getStartAddressLatitude());
        entity.setEndAddress(param.getEndAddress());
        entity.setEndAddressLongitude(param.getEndAddressLongitude());
        entity.setEndAddressLatitude(param.getEndAddressLatitude());
        entity.setDropOffArea(param.getDropOffArea());
        entity.setDropOffAreaLongitude(param.getDropOffAreaLongitude());
        entity.setDropOffAreaLatitude(param.getDropOffAreaLatitude());
        entity.setDesttime(DateUtil.parseLocalDateTime(param.getDesttime()));
        entity.setStartServiceTime(DateUtil.parseLocalDateTime(param.getStartServiceTime()));
        entity.setEndServiceTime(DateUtil.parseLocalDateTime(param.getEndServiceTime()));
        entity.setIdStation(param.getIdStation());
        entity.setReferenceDistance(oprv.getOrderDistance());//预估花费距离
        entity.setEstimatedTime(oprv.getSpendTime());//预估花费时间
        entity.setEstimatedMoney(oprv.getTotalPrice());//预估花费金额
        //entity.setGpsPn(param.getGpsPn());
        //entity.setPayMoney(param.getPayMoney());
        //entity.setCouponCode(param.getCouponCode());
        //entity.setCouponDiscount(param.getCouponDiscount());
        entity.setOrderSource(param.getOrderSource());
        //entity.setPaymentType(param.getPaymentType());

        entity.setOrderMemo(param.getOrderMemo());
        //entity.setDriverMemo(param.getDriverMemo());
        //entity.setPassengerMemo(param.getPassengerMemo());

        IntercityOrderEntity returnEntity = orderRepository.save(entity);

        //追加订单状态
        IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
        orderStatus.setIdOrder(entity.getIdOrder());
        orderStatus.setStatus(entity.getStatus());
        orderStatus.setCreateBy("capacity");
        orderStatus.setMemo("运力商系统录入订单");
        orderStatusHistoryRepository.save(orderStatus);

        //订单结果(未完成)
        //判断一口价生成账单
        IntercityOrderResultEntity resultEntity = icOrderResultRepository.findByIdOrder(entity.getIdOrder());
        if (resultEntity == null)
            resultEntity = OrderConvertor.INSTANCE.icOrderReslutConvert(param);

        resultEntity.setIdOrder(entity.getIdOrder());
        resultEntity.setOrderDistance(oprv.getOrderDistance());
        resultEntity.setOrderReferenceDistance(oprv.getOrderDistance());
        resultEntity.setOrderSpendTime(oprv.getSpendTime());
        resultEntity.setIdServicePriceSetting(oprv.getIdServicePriceType());
        resultEntity.setOrderBasePrice(oprv.getBasePrice());
        resultEntity.setOrderPerKilometres(oprv.getPerKilometres());
        resultEntity.setOrderPerTime(oprv.getPerTime());
        resultEntity.setOverMileMoney(oprv.getOverMileMoney());
        resultEntity.setOverTimeMoney(oprv.getOverTimeMoney());
        resultEntity.setBaseTotalMoney(oprv.getTotalPrice());
        icOrderResultRepository.save(resultEntity);

        return returnEntity;
    }

    /**
     * 创建城际订单
     * @param param
     * @return
     */
    @Override
    public IntercityOrderEntity updateIntercityOrder(IntercityCreateOrderParam param) {
        //1，乘客账户存在时，前端未传值的情况下，取得乘客信息放到对应参数当中
        MemberEntity member = memberService.createNewMember(param.getUserMobile());

        //定价ID未知时，取得并保存
        IntercityPriceParam price = new IntercityPriceParam();
        StringBuffer origins = new StringBuffer(param.getStartAddressLatitude()).append(",").append(param.getStartAddressLongitude());
        StringBuffer dest = new StringBuffer(param.getEndAddressLatitude()).append(",").append(param.getEndAddressLongitude());
        price.setIdLine(param.getIdLine());
        price.setOrigins(origins.toString());
        price.setDestinations(dest.toString());
        price.setPassengerNumber(param.getPassengerNumber());
        price.setCarpoolType(param.getCarpoolType());
        price.setIdStation(param.getIdStation());
        OrderPriceVO oprv = calIntercityPrice(price);
        //保存订单信息
//        IntercityOrderEntity entity = Convert.convert(IntercityOrderEntity.class, param);
        if (StringUtil.isBlank(param.getIdOrder()))
            throw new BusinessException(5002,"订单号参数未传入");
        IntercityOrderEntity entity = orderRepository.findById(param.getIdOrder()).get();

        entity.setIdTask(param.getIdTask());
        entity.setIdLine(param.getIdLine());
        entity.setAdditionalMoney(param.getAdditionalMoney());
        entity.setStatus(param.getStatus());
        entity.setIsContact(param.getIsContact());
        entity.setIdOrder(param.getIdOrder());
        entity.setIdMember(member.getIdMember());
        entity.setIdCorporate(param.getIdCorporate());
        entity.setCorporateName(param.getCorporateName());
        entity.setIdDriver(param.getIdDriver());
        entity.setIdFranchisee(param.getIdFranchisee());
        entity.setFullName(param.getFullName());
        entity.setCarpoolType(param.getCarpoolType());
        entity.setIdServiceType(Constants.Service_Type.get(entity.getCarpoolType()));// 数据库默认99
        entity.setIdVehicleType(param.getIdVehicleType());
        entity.setModel(param.getModel());
//        String id_service_price_type = StringUtil.isBlank(param.getIdServicePriceType()) ? param.getIdServicePriceType() : oprv.getIdServicePriceType();
        entity.setIdServicePriceType(oprv.getIdServicePriceType());// 含义未知，沿用过往旧数据21
        entity.setOrderType(param.getOrderType());// 订单类型无效
        entity.setIdRelationshipOrder(param.getIdRelationshipOrder());
        entity.setDriverSubsidy(param.getDriverSubsidy());
        entity.setDriverNoLoadSubsidy(param.getDriverNoLoadSubsidy());
        entity.setUserName(param.getUserMobile());
        entity.setUserMobile(param.getUserMobile());
        entity.setPassengerName(param.getUserName());//传值下单用户名
        entity.setPassengerMobile(param.getPassengerMobile());
        entity.setPassengerNumber(param.getPassengerNumber());
        entity.setPlateNumber(param.getPlateNumber());
        entity.setVehicleInfo(param.getVehicleInfo());
        entity.setAppointmentTime(DateUtil.parseLocalDateTime(param.getAppointmentTime()));
        entity.setCutOffTime(DateUtil.parseLocalDateTime(param.getCutOffTime()));
        entity.setAssignTime(DateUtil.parseLocalDateTime(param.getAssignTime()));
        entity.setDriverLongitude(param.getDriverLongitude());
        entity.setDriverLatitude(param.getDriverLatitude());
        entity.setDeptime(DateUtil.parseLocalDateTime(param.getDeptime()));
        entity.setStartAddress(param.getStartAddress());
        entity.setStartAddressLongitude(param.getStartAddressLongitude());
        entity.setStartAddressLatitude(param.getStartAddressLatitude());
        entity.setEndAddress(param.getEndAddress());
        entity.setEndAddressLongitude(param.getEndAddressLongitude());
        entity.setEndAddressLatitude(param.getEndAddressLatitude());
        entity.setDropOffArea(param.getDropOffArea());
        entity.setDropOffAreaLongitude(param.getDropOffAreaLongitude());
        entity.setDropOffAreaLatitude(param.getDropOffAreaLatitude());
        entity.setDesttime(DateUtil.parseLocalDateTime(param.getDesttime()));
        entity.setStartServiceTime(DateUtil.parseLocalDateTime(param.getStartServiceTime()));
        entity.setEndServiceTime(DateUtil.parseLocalDateTime(param.getEndServiceTime()));
        entity.setIdStation(param.getIdStation());
        entity.setReferenceDistance(oprv.getOrderDistance());//预估花费距离
        entity.setEstimatedTime(oprv.getSpendTime());//预估花费时间
        entity.setEstimatedMoney(oprv.getTotalPrice());//预估花费金额
        entity.setGpsPn(param.getGpsPn());
        entity.setPayMoney(param.getPayMoney());
        entity.setCouponCode(param.getCouponCode());
        entity.setCouponDiscount(param.getCouponDiscount());
        entity.setOrderSource(param.getOrderSource());
        entity.setPaymentType(param.getPaymentType());
        int paymentStatus = (param.getPaymentStatus() == null) ? Constants.PaymentStatus.UN_PAY : param.getPaymentStatus();
        entity.setPaymentStatus(paymentStatus);
        int paymentRequitment = (param.getPaymentRequitment() == null) ? Constants.PaymentRequitment.IN_ADVANCE : param.getPaymentRequitment();
        entity.setPaymentRequitment(paymentRequitment);
        entity.setTranFlag(param.getTranFlag());
        entity.setPassengerConfirmArrival(param.getPassengerConfirmArrival());//
        int status = Constants.OrderStatus.ORDER_STATUS_CREATED;
        if (param.getStatus() != null)
            status = param.getStatus();
        entity.setStatus(status);
        entity.setDivideAccountsStatus(param.getDivideAccountsStatus());
        entity.setOrderMemo(param.getOrderMemo());
        entity.setDriverMemo(param.getDriverMemo());
        entity.setPassengerMemo(param.getPassengerMemo());;
        entity.setUpdateBy(Constants.Def_CreateBy);
        IntercityOrderEntity returnEntity = orderRepository.save(entity);

        //订单结果(未完成)
        //判断一口价生成账单
        IntercityOrderResultEntity resultEntity = icOrderResultRepository.findByIdOrder(entity.getIdOrder());
        if (resultEntity == null)
            resultEntity = OrderConvertor.INSTANCE.icOrderReslutConvert(param);

        resultEntity.setIdOrder(entity.getIdOrder());
        resultEntity.setOrderDistance(oprv.getOrderDistance());
        resultEntity.setOrderReferenceDistance(oprv.getOrderDistance());
        resultEntity.setOrderSpendTime(oprv.getSpendTime());
        resultEntity.setIdServicePriceSetting(oprv.getIdServicePriceType());
        resultEntity.setOrderBasePrice(oprv.getBasePrice());
        resultEntity.setOrderPerKilometres(oprv.getPerKilometres());
        resultEntity.setOrderPerTime(oprv.getPerTime());
        resultEntity.setOverMileMoney(oprv.getOverMileMoney());
        resultEntity.setOverTimeMoney(oprv.getOverTimeMoney());
        resultEntity.setBaseTotalMoney(oprv.getTotalPrice());
        icOrderResultRepository.save(resultEntity);

        return returnEntity;
    }

     /**
     * 获取城际线路信息
     * @param cityCode
     * @return
     */
    @Override
    public HashMap getCityLines(String cityCode) {
        HashMap<String, List<IntercityLineEntity>> returns = new HashMap<>();

        //全线路数据取得
        List<CityLineEntity> lstCityLine = cityLineRepository.findByCityCode(cityCode);
        if (lstCityLine.size()==0){
            throw new BusinessException(4001,"没有设置相关线路");
        }
        //ArrayList<IntercityLineEntity> allList = new ArrayList<>();
        ArrayList<IntercityLineEntity> startList = new ArrayList<>();
        ArrayList<IntercityLineEntity> endList = new ArrayList<>();

        for (CityLineEntity cityLine:lstCityLine){
            List<IntercityLineEntity> listStart = lineRepository.findByIdCityLineAndStartCityCode(cityCode,cityLine.getIdCityLine());
            startList.addAll(listStart);
            List<IntercityLineEntity> listEnd = lineRepository.findByIdCityLineAndEndCityCode(cityCode,cityLine.getIdCityLine());
            endList.addAll(listEnd);
            //allList.addAll(listStart);
            //allList.addAll(listEnd);
        }

        returns.put("start",startList);
        returns.put("end",endList);
        //returns.put("all",allList);

        return returns;
    }

    /**
     * 根据城际定制线路列表
     * @param cityCode
     * @return
     */
    @Override
    public HashMap getCustomCityLines(String cityCode) {
        HashMap<String, List<CustomCityLineVO>> returns = new HashMap<>();

        //全线路数据取得
        List<CityLineEntity> lstCityLine = cityLineRepository.findByCityCode(cityCode);
        if (lstCityLine.size()==0){
            throw new BusinessException(4001,"没有设置相关线路");
        }
        //ArrayList<CustomCityLineVO> allList = new ArrayList<>();
        ArrayList<CustomCityLineVO> startList = new ArrayList<>();
        ArrayList<CustomCityLineVO> endList = new ArrayList<>();

        for (CityLineEntity cityLine:lstCityLine){
            List<CustomCityLineVO> listStart = lineRepository.findVoByIdCityLineAndStartCityCode(cityLine.getStationRegionCode(),cityLine.getIdCityLine());
            if (listStart.size()==0){
                listStart = lineRepository.findVoByIdCityLineAndStartCityCode(cityLine.getCityCode(),cityLine.getIdCityLine());
            }
            startList.addAll(listStart);
            List<CustomCityLineVO> listEnd = lineRepository.findVoByIdCityLineAndEndCityCode(cityLine.getStationRegionCode(),cityLine.getIdCityLine());
            if (listEnd.size()==0){
                listEnd = lineRepository.findVoByIdCityLineAndEndCityCode(cityLine.getCityCode(),cityLine.getIdCityLine());
            }
            endList.addAll(listEnd);

            //allList.addAll(listStart);
            //allList.addAll(listEnd);
        }
        //接送站反过来设定
        returns.put("start",startList);
        returns.put("end",endList);
        //returns.put("all",allList);

        return returns;
    }

    @Override
    public PagingResultVO<IcSearchVO> dispatherIcOrderSearch(DispatcherSearchOrderParam param, Boolean forHistory) {

        //param.setHistoryFlg(forHistory);
        IcListParam icListParam = OrderConvertor.INSTANCE.convert2IcParam(param);
        //log.info("IcSearchVO List:"+ JSON.toJSONString(lst));
        return new PagingResultVO(orderMapper.searchWithConditionsAndPagingTotal(icListParam), orderMapper.searchWithConditionsAndPaging(icListParam));
    }

    /**
     * 获取今日录单信息
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<IcListNewVO> getNewIcOrderList(IcListNewParam param) {
//        return IntercityConvertor.INSTANCE.convert(intercityService.searchWithConditionsAndPaging(param));
//        param.setCreatTimeF(DateUtil.getStartTimeOfDay());
//        param.setCreatTimeE(DateUtil.getEndTimeOfDay());
        param.setIdLineList();
//        param.setAppointmentTime(DateUtil.getStartTimeOfDay());
        param.setAppointmentTimeF(DateUtil.getYestodayLocalDate());;
        if (param.getHourRange()==null){
            param.setHourRange(Constants.OrderFastSearchType.ALl);
        }
        switch (param.getHourRange()) {
            case Constants.OrderFastSearchType.ALl:
                break;
//            case Constants.OrderModuleType.EXPRESS:
//                break;
            default:
                LocalDateTime appointmentTimeE = DateUtil.getXHoursLaterDateTime(param.getHourRange());
                param.setAppointmentTimeE(cn.hutool.core.date.DateUtil.format(appointmentTimeE,Constants.DATE_FORMAT));
                param.setAppointmentTimeF(DateUtil.getNowLocalDate());;
                break;
        }
        return new PagingResultVO<>(orderMapper.getNewIcOrderListTotal(param),orderMapper.getNewIcOrderList(param));
    }

    /**
     * 更改订单价格
     * @param param
     * @return
     */
    @Override
    public Boolean reCalculatePrice(IntercityRePriceParam param) {
        boolean result = orderRepository.updatePrice(param.getOrderPrice(), param.getIdOrder()) == 1;
        if (result) {
            // TODO 价格更改记录

        }
        return result;
    }

    /**
     * 更换派遣司机
     * @param param
     * @return
     */
    @Override
    public Boolean reDispatchDriver(DispatchDriverParam param) {
        // todo@2023.6.4 改派司机任务信息如何刷新？
        // 检查订单状态
        IntercityOrderEntity order = orderRepository.findByIdOrder(param.getIdOrder());
        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        if (order.getStatus() > Constants.OrderStatus.ORDER_STATUS_GOTO_RESERVATION)
            throw new BusinessException(5002, "订单已经在执行，不能转派，如需改派请去服务订单列表强制改派");

        if (StringUtil.isBlank(param.getIdDriver()))
            throw new BusinessException(5002, "指定司机ID不能为空");

        DriverInfoVO driver = driverService.driverInfo(param.getIdDriver());
        if (driver == null)
            throw new BusinessException(5002, "司机不存在，请检查参数idDriver是否正确");

        // 司机账户冻结不能派单
        if (driver.getStatus() == Constants.DriverStatus.FREEZE)
            throw new BusinessException(5002,"司机账户被冻结,不能派单");

        // 实时单
        if (Constants.OrderType.REALTIME == order.getOrderType() && driver.getStatus() != Constants.DriverStatus.ONLINE)
            throw new BusinessException(5002,"实时单只能指派空闲司机");

        if (!vehicleService.verifyVehicleType(driver.getIdVehicleType(), order.getIdVehicleType()))
            throw new BusinessException(5002, "车辆类型不匹配，无法派单！");

        String driverName = StringUtil.isNotBlank(driver.getNickName()) ? driver.getNickName() : driver.getRealName();
        String driverInfo = driverName + "/" + driver.getDriverMobile();

        String dispatchIdDriver = StringUtil.isBlank(order.getIdDriver()) ? "" : order.getIdDriver();
        boolean isSendMessage = param.getIdDriver().equals(dispatchIdDriver);

        //接受同程的订单 司机派单或者改派
        if (Constants.OrderSource.TONGCHENG_RIDE == order.getOrderSource() && !isSendMessage) {
            OrderStatusDTO dto = new OrderStatusDTO()
                    .setStatus(TongChengConstants.ELong_OrderType.get(Constants.OrderStatus.ORDER_STATUS_ACCEPTED))
                    .setDriverName(driverName)
                    .setDriverPhone(driver.getDriverMobile())
                    .setVehiclePlateNum(driver.getPlateNumber())
                    .setVehicleColor(driver.getColor())
                    .setVehicleModel(driver.getModel())
                    .setVehicleBrand(driver.getBrand());

            dto.setOrderId(order.getExternalOrderId());
            dto.setSupplierOrderId(order.getIdOrder());

            String idChannel = authService.findIdChannel(null, order.getIdFranchisee());
            if (StringUtil.isBlank(idChannel))
                throw new BusinessException(5002, "未找到对应的同程渠道，请检查渠道ID");

            cacheRedis.writeOrderDriverValue(order.getIdOrder(), JSON.toJSONString(driver));

            ResultVO resultVO = callback.orderStatus(idChannel, dto);
            if (resultVO.getStatus() != 200)
                throw new BusinessException(5002, "同程接口回调失败，请重新执行");
        }

        boolean result = orderRepository.updateDriver(param.getIdDriver(),
                driver.getIdFleet(),
                driverInfo,
                Constants.OrderStatus.ORDER_STATUS_ACCEPTED,
                driver.getPlateNumber(),
                driver.getVehicleName(),
                LocalDateTime.now(),
                param.getIdOrder()) == 1;

        if (!result){
            return false;
        }

//        if (result) {
//            icDispatchRepository.save(new IntercityOrderDispatchEntity(param));
//        }

        // 3.更新订单系统派单时间
//        orderRepository.updateAssignTime(param.getIdOrder(), LocalDateTime.now());

//        // 4.更新订单用车类型（0：实时 1：预约）
//        orderRepository.updateOrderType(param.getIdOrder(), orderType);

        if (Constants.OrderSource.TONGCHENG_RIDE != order.getOrderSource()) {
            int orderType = Constants.OrderType.APPOINTMENT;
            Duration dur = Duration.between(LocalDateTime.now(), order.getAppointmentTime());
            long minute = dur.toMinutes();
            //两小时以前
            if (minute <= 120) {
                orderType = Constants.OrderType.REALTIME;
            }

            // 实时单
            if (Constants.OrderType.REALTIME == orderType) {
                //更新司机状态
                result = driverRepository.driverUpdateStatus(Constants.DriverStatus.TAKE_ORDER, param.getIdDriver()) == 1;
                if (!result) {
                    return false;
                }
                //更新司机上线任务状态
                result = driverRepository.driverUpdateOperationStatus(Constants.DriverOperationStatus.EXPRESS_ONLINE, param.getIdDriver()) == 1;
                if (result) {
                    icDispatchRepository.save(new IntercityOrderDispatchEntity(param));
                }
            }
        }

        // TODO 订单操作记录
        IntercityOrderOperationHistory oph = new IntercityOrderOperationHistory();
        oph.setIdOrder(param.getIdOrder());
        oph.setIdFranchisee(order.getIdFranchisee());
        oph.setCreateBy(param.getDispatcher());
        oph.setOperation(String.format(MessageTemplate.ExOrderOperation.DISPATCH_ORDER,
                param.getDispatcher(),
                param.getIdOrder(),
                driver.getRealName()));
        oph.setOperationFlag(0);
        icOrderOperationHistoryRepository.save(oph);

        //追加订单状态
        IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
        orderStatus.setIdOrder(order.getIdOrder());
        orderStatus.setStatus(Constants.OrderStatus.ORDER_STATUS_ACCEPTED);
        orderStatus.setCreateBy(Constants.Def_CreateBy);
        orderStatus.setMemo(oph.getOperation());
        orderStatusHistoryRepository.save(orderStatus);

        return result;
    }

    /**
     * 司机派单(城际)
     * @param param
     * @return
     */
    @Transactional
    @Override
    public Boolean dispatchDriver(DispatchDriverParam param) {
        boolean result = false;
        IntercityOrderEntity order = orderRepository.findByIdOrder(param.getIdOrder());

        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        if (order.getStatus() >= Constants.OrderStatus.ORDER_STATUS_CANCEL)
            throw new BusinessException(5002, "订单已取消，无法派单");

        DriverInfoVO driverInfoVO = driverService.driverInfo(param.getIdDriver());
        if (driverInfoVO == null)
            throw new BusinessException(5002, "司机不存在，请检查参数idDriver是否正确");

        //VehicleTypeEntity vt = vehicleTypeRepository.findByIdDriver(param.getIdDriver());
        Integer carpoolType = order.getCarpoolType();
        if (Constants.OrderCarpoolType.Chartered == carpoolType){
            //用车类型不匹配 TODO 车型可以向上派单不能向下派单
            if (!vehicleService.verifyVehicleType(driverInfoVO.getIdVehicleType(), order.getIdVehicleType()))
                throw new BusinessException(5002, "车辆类型不匹配，无法派单！");
        }

        int orderType = Constants.OrderType.APPOINTMENT;
        Duration dur = Duration.between(LocalDateTime.now(),order.getAppointmentTime());
        long minute = dur.toMinutes();
        //两小时以前
        if(minute<=120){
            orderType = Constants.OrderType.REALTIME;
        }

        // 实时单
        if (Constants.OrderType.REALTIME == orderType) {
            //派订单给任务
            OrderParam orderParam = new OrderParam();
            orderParam.setIdDriver(param.getIdDriver());
            orderParam.setModuleType(StringUtil.orderType(param.getIdOrder()));
            JobPlatformEntity task = jobPlatformBiz.assignOrderToJob(order, orderParam);

            // 1.更新订单状态任务ID
            orderRepository.updateIdTask(param.getIdOrder(),task.getIdTask(),param.getDispatcher());
        }

//        DriverEntity driver = driverRepository.findByIdDriver(param.getIdDriver());
//        if (driver == null)
//            throw new BusinessException(5002, "司机不存在，请检查参数idDriver是否正确");

        //DriverProfileEntity driverProfile = driverProfileRepository.findByIdDriverProfile(driver.getIdDriverProfile());
        String driverName = StringUtil.isNotBlank(driverInfoVO.getNickName()) ? driverInfoVO.getNickName() : driverInfoVO.getRealName();
        String driverInfo = driverName + "/" + driverInfoVO.getDriverMobile();

        if (StringUtil.isBlank(order.getIdDriver()) || !order.getIdDriver().equals(param.getIdDriver())) {
            //接受同程的订单 司机派单或者改派
            if (Constants.OrderSource.TONGCHENG_RIDE == order.getOrderSource()) {
                OrderStatusDTO dto = new OrderStatusDTO()
                        .setStatus(TongChengConstants.ELong_OrderType.get(Constants.OrderStatus.ORDER_STATUS_ACCEPTED))
                        .setDriverName(driverInfoVO.getRealName())
                        .setDriverPhone(driverInfoVO.getDriverMobile())
                        .setVehiclePlateNum(driverInfoVO.getPlateNumber())
                        .setVehicleColor(driverInfoVO.getColor())
                        .setVehicleModel(driverInfoVO.getModel())
                        .setVehicleBrand(driverInfoVO.getBrand());

                dto.setOrderId(order.getExternalOrderId());
                dto.setSupplierOrderId(order.getIdOrder());

                String idChannel = authService.findIdChannel(null, order.getIdFranchisee());
                if (StringUtil.isBlank(idChannel))
                    throw new BusinessException(5002, "未找到对应的同程渠道，请检查渠道ID");

                ResultVO resultVO = callback.orderStatus(idChannel, dto);
                if (resultVO.getStatus() != 200)
                    throw new BusinessException(5002, "同程接口回调失败，请重新执行");
            }
        }

//        //司机车辆信息取得
//        VehicleEntity dv = vehicleRepository.findByIdDriver(param.getIdDriver());
        // 2.更新订单司机信息
        result = orderRepository.updateDriver(param.getIdDriver(),
                driverInfoVO.getIdFleet(),
                driverInfo,
                Constants.OrderStatus.ORDER_STATUS_ACCEPTED,
                driverInfoVO.getPlateNumber(),
                driverInfoVO.getVehicleName(),
                LocalDateTime.now(),
                param.getIdOrder()) == 1;

        if (!result){
            return false;
        }

        // 3.更新订单系统派单时间
//        orderRepository.updateAssignTime(param.getIdOrder(), LocalDateTime.now());

//        // 4.更新订单用车类型（0：实时 1：预约）
//        orderRepository.updateOrderType(param.getIdOrder(), orderType);

        // 实时单
        if (Constants.OrderType.REALTIME == orderType) {
            //更新司机状态
            result = driverRepository.driverUpdateStatus(Constants.DriverStatus.TAKE_ORDER, param.getIdDriver())== 1;
            if (!result){
                return false;
            }
            //更新司机上线任务状态
            result = driverRepository.driverUpdateOperationStatus(Constants.DriverOperationStatus.EXPRESS_ONLINE, param.getIdDriver()) == 1;
            if (result){
                icDispatchRepository.save(new IntercityOrderDispatchEntity(param));
            }
        }

        // TODO 订单操作记录
        IntercityOrderOperationHistory oph = new IntercityOrderOperationHistory();
        oph.setIdOrder(param.getIdOrder());
        oph.setIdFranchisee(order.getIdFranchisee());
        oph.setCreateBy(param.getDispatcher());
        oph.setOperation(String.format(MessageTemplate.ExOrderOperation.DISPATCH_ORDER,
                param.getDispatcher(),
                param.getIdOrder(),
                driverInfoVO.getRealName()));
        oph.setOperationFlag(0);
        icOrderOperationHistoryRepository.save(oph);

        //追加订单状态
        IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
        orderStatus.setIdOrder(order.getIdOrder());
        orderStatus.setStatus(Constants.OrderStatus.ORDER_STATUS_ACCEPTED);
        orderStatus.setCreateBy(Constants.Def_CreateBy);
        orderStatus.setMemo(oph.getOperation());
        orderStatusHistoryRepository.save(orderStatus);

        return true;
    }

    /**
     * 取消快车司机派单
     * @param param
     * @return
     */
    @Transactional
    @Override
    public Boolean unDispatchDriver(DispatchDriverParam param) {

        boolean result = false;

        List<String> listIdOrder = StringUtil.StringToList(param.getIdOrder());

        for (String idOrder:listIdOrder) {
            DispatchDriverParam orderParam = new DispatchDriverParam();
            orderParam.setIdOrder(idOrder);
            orderParam.setIdDriver(param.getIdDriver());
            orderParam.setDispatcher(param.getDispatcher());
            unDispatchDriverByOrderId(orderParam);
        }

        return true;
    }

    private void unDispatchDriverByOrderId(DispatchDriverParam param){
        IntercityOrderEntity order = orderRepository.findByIdOrder(param.getIdOrder());
        if (order==null){
            throw new BusinessException(4001,"订单不存在");
        }
        if(!order.getIdDriver().equals(param.getIdDriver()))
            throw new BusinessException(4001,"订单不属于当前司机");

        // 1.更新订单状态任务ID
        orderRepository.updateIdTask(param.getIdOrder(),null,param.getDispatcher());

        // 2.更新订单司机信息
        orderRepository.updateDriver(null,null, null, Constants.OrderStatus.ORDER_STATUS_CREATED,
                null,null, null, param.getIdOrder());

        // 3.更新订单系统派单时间
        //orderRepository.updateAssignTime(param.getIdOrder(), null);

        // 更新订单状态 Todo 需要？
        driverRepository.driverUpdateStatus(Constants.DriverStatus.ONLINE, param.getIdDriver());
        driverRepository.driverUpdateOperationStatus(Constants.DriverOperationStatus.EXPRESS_ONLINE, param.getIdDriver());
        icDispatchRepository.save(new IntercityOrderDispatchEntity(param));

        // TODO 订单操作记录
        IntercityOrderOperationHistory oph = new IntercityOrderOperationHistory();
        oph.setIdOrder(param.getIdOrder());
        oph.setIdFranchisee(order.getIdFranchisee());
        oph.setCreateBy(param.getDispatcher());
        oph.setOperation(String.format(MessageTemplate.ExOrderOperation.CANCEL_ORDER,
                param.getDispatcher(),
                param.getIdOrder()));
        oph.setOperationFlag(0);
        icOrderOperationHistoryRepository.save(oph);

        //追加订单状态
        IntercityOrderStatusHistoryEntity orderStatus = new IntercityOrderStatusHistoryEntity();
        orderStatus.setIdOrder(param.getIdOrder());
        orderStatus.setStatus(Constants.OrderStatus.ORDER_STATUS_CREATED);
        orderStatus.setCreateBy(Constants.Def_CreateBy);
        orderStatus.setMemo(oph.getOperation());
        orderStatusHistoryRepository.save(orderStatus);

        // 任务ID不为空
        if (StringUtil.isNotBlank(order.getIdTask())){
            //实时订单
            JobPlatformEntity task = jobRepository.findByIdDriver(param.getIdDriver());
            //IntercityDriverTaskEntity task = icDriverTaskRepository.findByIdDriverAndTaskType(param.getIdDriver(),Constants.OrderType.REALTIME);
            if (task==null){
                throw new BusinessException(4001,"任务异常");
            }
            // 在乘人数(已在车上人数+将要乘车人数，以下车人数不在内）+ 当前派单的订单人数
            Integer passengers_incar_number = task.getPassengersIncarNumber() - order.getPassengerNumber();
            // 预估金额
            Float taskSumMoney = NumUtil.getFloat(task.getTaskSumMoney()) - NumUtil.getFloat(order.getEstimatedMoney());
            // 任务额外金额
            Float taskAdditionalMoney = NumUtil.getFloat(task.getTaskAdditionalMoney()) - NumUtil.getFloat(order.getAdditionalMoney());
            // 任务优惠金额
            Float task_coupon_money = NumUtil.getFloat(task.getTaskCouponMoney()) - NumUtil.getFloat(order.getCouponDiscount());
            //更新任务信息(派单完成)
            //task.setStatus(Constants.TaskStatus.DISPATCH_COMPLETE);
            task.setPassengersIncarNumber(passengers_incar_number);
            task.setTaskSumMoney(taskSumMoney);
            task.setTaskAdditionalMoney(taskAdditionalMoney);
            task.setTaskCouponMoney(task_coupon_money);
            task.setUpdateBy(param.getDispatcher());
            jobRepository.saveAndFlush(task);
        }
    }

    /**
     * 取消订单
     * @param orderId
     * @return
     */
    @Override
    public Boolean cancelOrder(String orderId) {
        log.info("cancel order service 执行");

        // 检查订单状态
        IntercityOrderEntity order = orderRepository.findByIdOrder(orderId);
        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        if (order.getStatus() > Constants.OrderStatus.ORDER_STATUS_ARRIVED)
            throw new BusinessException(5002, "订单已开始服务，无法删除。");

        if (order.getOrderSource() == Constants.OrderSource.TONGCHENG_RIDE) {
            if (StringUtil.isNotBlank(order.getIdDriver())) {
                log.info("cancel order service 同程接口执行");
                DriverInfoVO vo = driverService.driverInfo(order.getIdDriver());

                //同程路径：/elong/order/driver/cancel
                OrderStatusDTO dto = (OrderStatusDTO) new OrderStatusDTO()
                        .setStatus(TongChengConstants.ELong_OrderType.get(Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED))
                        .setDriverName(vo.getRealName())
                        .setDriverPhone(vo.getDriverMobile())
                        .setVehiclePlateNum(vo.getPlateNumber())
                        .setVehicleColor(vo.getColor())
                        .setVehicleModel(vo.getModel())
                        .setVehicleBrand(vo.getBrand())
                        .setCancelType(TongChengConstants.CancelType.CUSTOMER_SERVICE)
                        .setCancelReason("因司机临时有变系统无法派单");

                dto.setOrderId(order.getExternalOrderId());
                dto.setSupplierOrderId(order.getIdOrder());

                String idChannel = authService.findIdChannel(null, order.getIdFranchisee());
                if (StringUtil.isBlank(idChannel))
                    throw new BusinessException(5002, "未找到对应的同程渠道，请检查渠道ID");

                ResultVO resultVO = callback.orderStatus(idChannel, dto);
                if (resultVO.getStatus() != 200)
                    throw new BusinessException(5002, "同程取消失败"+resultVO.getMessage());
            }
        }

        boolean result = orderRepository.updateOrderStatus(orderId, Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED) == 1;
        if (result) {

            //订单取消历史
            IcOrderCancelHistoryEntity icCancel = new IcOrderCancelHistoryEntity();
            icCancel.setIdOrder(orderId);
            icCancel.setOperationType(Constants.OrderOperatorType.ALLIANCE);
            icCancel.setIdOperation("");
            String reason = String.format("同程订单号：%s%s", order.getExternalOrderId(), "无法处理");
            icCancel.setReason(reason);
            //todo 取消原因编码
            icCancel.setReasonCode(Constants.OrderCancelType.USER_CANCEL);
            icCancel.setMemo(MessageTemplate.OrderStatus.USER_CANCEL);
            orderCancelHistoryRepository.save(icCancel);
            log.debug("订单取消历史执行成功");

            //添加订单状态变化历史
            IntercityOrderStatusHistoryEntity icStatus = new IntercityOrderStatusHistoryEntity();
            icStatus.setIdOrder(orderId);
            icStatus.setStatus(Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED);
            icStatus.setCreateBy(Constants.Def_CreateBy_ELong);
            icStatus.setMemo(String.format(MessageTemplate.OrderStatus.SYSTEM_CANCEL, orderId));
            orderStatusHistoryRepository.save(icStatus);
            log.debug("订单取消状态变化历史执行成功");

//            // TODO 取消记录
//            // TODO 订单操作履历
//            IntercityOrderOperationHistory oph = new IntercityOrderOperationHistory();
//            oph.setIdOrder(orderId);
//            oph.setIdFranchisee("");
//            oph.setCreateBy(Constants.Def_CreateBy);
//            oph.setOperation(String.format(MessageTemplate.ExOrderOperation.CANCEL_ORDER, Constants.Def_CreateBy,orderId));
//            oph.setOperationFlag(0);
//            oph.setIdOperation("1");
//            icOrderOperationHistoryRepository.save(oph);
        }
        return result;
    }

    @Override
    public OrderVO virtualAcceptOrder(String idOrder, String idDriver) {
        IntercityOrderEntity order = orderRepository.findById(idOrder).orElse(null);
        if (order == null)
            throw new BusinessException(5002, "订单不存在，请检查参数idOrder是否正确");

        if (order.getStatus() > Constants.OrderStatus.ORDER_STATUS_ACCEPTED)
            throw new BusinessException(5002,"订单已开始服务，无法虚拟接单。");

        if (order.getStatus() == Constants.OrderStatus.ORDER_STATUS_ACCEPTED &&
                StringUtil.isNotBlank(order.getIdDriver())) {
            if (order.getVirtualOrderAccepted() == 1) {
                return OrderConvertor.INSTANCE.icOrderToView(order);
            } else {
                throw new BusinessException(5002, "订单已安排司机，如需更换司机请执行改派才做。");
            }
        }

        if (StringUtil.isBlank(idDriver)) {
            idDriver = TongChengConstants.ELong_VirtualDriver.get(order.getIdFranchisee());
            if (StringUtil.isBlank(idDriver) && StringUtil.isNotBlank(order.getIdFranchisee())) {
                DriverEntity entity = driverService.findDriverByIdFranchiseeWithRand(order.getIdFranchisee());
                if (entity == null)
                    throw new BusinessException(5002, "未找到该加盟商有注册完整司机");
                else
                    idDriver = entity.getIdDriver();
            }
        }

        DriverInfoVO driverInfoVO = driverService.driverInfo(idDriver);

        String driverName = StringUtil.isNotBlank(driverInfoVO.getNickName()) ? driverInfoVO.getNickName() : driverInfoVO.getRealName();
        //String driverInfo = driverName + "/" + driverInfoVO.getDriverMobile();

        //接受同程的订单 司机派单或者改派
        if (Constants.OrderSource.TONGCHENG_RIDE == order.getOrderSource()) {
            OrderStatusDTO dto = new OrderStatusDTO()
                    .setStatus(TongChengConstants.ELong_OrderType.get(Constants.OrderStatus.ORDER_STATUS_ACCEPTED))
                    .setDriverName(driverName)
                    .setDriverPhone(driverInfoVO.getDriverMobile())
                    .setVehiclePlateNum(driverInfoVO.getPlateNumber())
                    .setVehicleColor(driverInfoVO.getColor())
                    .setVehicleModel(driverInfoVO.getModel())
                    .setVehicleBrand(driverInfoVO.getBrand());

            dto.setOrderId(order.getExternalOrderId());
            dto.setSupplierOrderId(order.getIdOrder());

            String idChannel = authService.findIdChannel(null, order.getIdFranchisee());
            if (StringUtil.isBlank(idChannel))
                throw new BusinessException(5002, "未找到对应的同程渠道，请检查渠道ID");
            cacheRedis.writeOrderDriverValue(idOrder, JSON.toJSONString(driverInfoVO));

            ResultVO resultVO = callback.orderStatus(idChannel, dto);
            if (resultVO.getStatus() != 200) {
                cacheRedis.clearOrderDriverValue(idOrder);
                throw new BusinessException(5002, "同程接口回调失败，请重新执行");
            }
        }

        //缓存保存
        order.setIdOrder(idOrder);
        order.setIdDriver(idDriver);
        order.setStatus(Constants.OrderStatus.ORDER_STATUS_ACCEPTED);
        order.setVirtualOrderAccepted(1);
        order.setDriverInfo(driverName);
        OrderVO vo = OrderConvertor.INSTANCE.icOrderToView(orderRepository.saveAndFlush(order));

        //vo有值后，清空缓存

        return vo;
    }

    @Override
    public OrderVO virtualAcceptOrder(DispatchParam param) {
        if (StringUtil.isBlank(param.getIdOrder()))
            throw new BusinessException(4001, "订单号idOrder不能为空");

        String idDriver;
        if (StringUtil.isNotBlank(param.getIdDriver())) {
            idDriver = param.getIdDriver();
        } else {
            idDriver = TongChengConstants.ELong_VirtualDriver.get(param.getIdFranchisee());
            if (StringUtil.isBlank(idDriver) && StringUtil.isNotBlank(param.getIdFranchisee())) {
                DriverEntity entity = driverService.findDriverByIdFranchiseeWithRand(param.getIdFranchisee());
                if (entity == null)
                    throw new BusinessException(5002, "未找到该加盟商有注册完整司机");
                else
                    idDriver = entity.getIdDriver();
            }
        }

        return this.virtualAcceptOrder(param.getIdOrder(), idDriver);
    }

    /**
     * 城际价格计算方法
     * @param param
     * @return
     */
    @Override
    public OrderPriceVO getIntercityPrice(IntercityPriceParam param) {

        RouteVO routeVO = routeRedis.calOrderDistance(
                param.getCoordinateType()
                , param.getOrigins(), param.getDestinations());

        if (routeVO == null)
            return null;

        float orderDistance = routeVO.getDistance();
        int duration = routeVO.getSpendTime();
//        param.setOrderDistance(routeVO.getDistance());
//        param.setSpendTime(routeVO.getSpendTime());

//        if (param.getCoordinateType() == Constants.CoordinateType.BD09LL.intValue()) {
//            RouteMatrixVO rm = routeMatrix.getDriving(param.getOrigins(), param.getDestinations());
//            if (rm == null || rm.getStatus() != 0) {
//                throw new BusinessException(5000,"百度地图调用失败,"+rm.getMessage());
//            }
//            orderDistance = rm.getDistanceValue();
//            duration = rm.getDurationValue();
//        } else {
//            DistanceMatrixVO rm = weMapTemplate.matrix().matrixDriving(param.getOrigins(), param.getDestinations());
//            //RouteMatrixVO rm = routeMatrix.getDriving(param.getOrigins(), param.getDestinations());
//            log.info("腾讯地图 DistanceMatrixVO:"+JSON.toJSONString(rm));
//            if (rm == null || rm.getStatus() != 0) {
//                throw new BusinessException(5000, "腾讯地图调用失败," + rm.getMessage());
//            }
//            orderDistance = rm.getDistanceValue();
//            duration = rm.getDurationValue();
//        }
        IntercityPriceEntity icp;
        if (StringUtil.isNotBlank(param.getIdFranchisee()))
            icp = icPriceRepository.findByIdFranchiseeAndIdLine(param.getIdFranchisee(), param.getIdLine());
        else
            icp = icPriceRepository.findByIdLine(param.getIdLine());

        if (ObjectUtil.isEmpty(icp))
            throw new BusinessException(5002, "当前线路[idLine:"+param.getIdLine()+"]未设置价格请联系管理员！");
        OrderPriceVO orderPrice = new OrderPriceVO();
        // 计算价格
        // 普通服务起步价
        float money = 0.0f;
        float basePrice = icp.getServicePrice().floatValue();
        BigDecimal dx1 = BigDecimal.valueOf(0.00);
        BigDecimal dt1 = BigDecimal.valueOf(0.00);
        if (orderDistance > icp.getMaxServiceMileage()) {
            BigDecimal distance = BigDecimal.valueOf(orderDistance - icp.getMaxServiceMileage());
            dx1 = NumberUtil.toBigDecimal(icp.getExceedingMileagePrice()).multiply(distance);
        }
//        if(icp.getWaitingTimePrice() != null){
//            if (duration > icp.getMaxWaitingTime()) { //TODO 等待时间未定
//                BigDecimal time = BigDecimal.valueOf(duration - icp.getMaxWaitingTime());
//                dt1 = NumberUtil.toBigDecimal(icp.getWaitingTimePrice()).multiply(time);
//            }
//        }
        if (param.getCarpoolType()!=null && param.getCarpoolType()==1){
            basePrice = icp.getCharteredCarPrice().floatValue();
        }else {
            basePrice = basePrice*param.getPassengerNumber();
        }
        float otherPrice = dx1.floatValue() + dt1.floatValue();
        money = basePrice + otherPrice;
        //
        orderPrice.setIdFranchisee(icp.getIdFranchisee());
        orderPrice.setOrderDistance(orderDistance);
        orderPrice.setSpendTime(duration);
        orderPrice.setIdServicePriceType(String.valueOf(icp.getIdIntercityLinePrice()));
        orderPrice.setTotalPrice(Convert.toFloat(new BigDecimal(money).setScale(2, RoundingMode.HALF_UP).toString()));
        orderPrice.setBasePrice(Convert.toFloat(new BigDecimal(basePrice).setScale(2, RoundingMode.HALF_UP).toString()));

        return orderPrice;
    }

    /**
     * 城际价格计算方法
     * @param param
     * @return
     */
    @Override
    public OrderPriceVO getCommonPrice(IntercityPriceParam param) {
        RouteVO routeVO = routeRedis.calOrderDistance(
                param.getCoordinateType()
                , param.getOrigins(), param.getDestinations());

        if (routeVO == null)
            return null;

        param.setOrderDistance(routeVO.getDistance());
        param.setSpendTime(routeVO.getSpendTime());

        boolean stp = false;
        ApplyStationEntity entity = null;
        if (StringUtil.isNotBlank(param.getIdStation()) && !param.getIdStation().equals("undefined"))
        {
            entity = applyStationRepository.findByIdStation(param.getIdStation());
            if (entity == null || !(entity.getStationType() == Constants.StaionType.INTERCITY
                    || entity.getStationType() == Constants.StaionType.ANY)) {
                throw new BusinessException(5002, "站点业务未开通，请核查是否开通业务");
            } else {
                if (entity != null && param.getInStation() == 0) {
                    if (param.getInStation() == Constants.InStationStatus.IN_STATION_STATUS_JIEZHAN) {
                        stp = (entity.getSendStationType() == 0);
                    } else if (param.getInStation() == Constants.InStationStatus.IN_STATION_STATUS_SONGZHAN) {
                        stp = (entity.getPickStationType() == 0);
                    }
                }
            }
        }

        OrderPriceVO orderPrice = null;
        if (stp) {
            orderPrice = icStpCalculate(param);
        } else {
            orderPrice = icCalculate(param);
        }

        return orderPrice;
    }

    /**
     * 条件检索查询
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<IcSearchVO> icOrderSearch(IcListParam param,Boolean forHistory) {
        //param.setHistoryFlg(forHistory);
        List<IcSearchVO> lst = orderMapper.searchWithConditionsAndPaging(param);
        //log.info("IcSearchVO List:"+ JSON.toJSONString(lst));
        return new PagingResultVO(orderMapper.searchWithConditionsAndPagingTotal(param), lst);
    }

    /**
     * 订单检索查询任务列表
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<IcSearchTaskVO> icOrderSearchTask(IcListTaskParam param) {
        List<IcSearchTaskVO> icSearchTaskVOS = orderMapper.searchTaskWithConditionsAndPaging(param);
        for (IcSearchTaskVO v:icSearchTaskVOS) {
            Float orderSumMoney = 0f;
            Integer passengerNumberSum = 0;
            if (v.getOrders()==null)continue;
            for (IcSearchTaskVO.Order order:v.getOrders()) {
                orderSumMoney=NumberUtil.add(orderSumMoney, order.getEstimatedMoney()).floatValue();
                passengerNumberSum+=order.getPassengerNumber();
            }
            v.setOrderSumMoney(orderSumMoney);
            v.setPassengerNumberSum(passengerNumberSum);
            v.setOrderSize(v.getOrders().size());
        }
        return new PagingResultVO(orderMapper.searchTaskWithConditionsAndPagingTotal(param), icSearchTaskVOS);
    }

    /**
     * 订单详情页
     * @param idOrder
     * @return
     */
    @Override
    public IcDetailVO icOrderDetail(String idOrder,Boolean forHistory) {
        List<IcDetailVO.StatusHistory> statusHistories = orderMapper.icOrderDetailHistory(idOrder);
        List<IcDetailVO.StatusHistory> statusHistoriesR = new ArrayList<>();
        IcDetailVO.Base base = null;
        if (forHistory){
            base = orderMapper.icOrderDetailBaseForHistory(idOrder);
        }else{
            base = orderMapper.icOrderDetailBase(idOrder);
        }
        if (base==null)throw new BusinessException(5002,"订单号不存在请检查");
        ArrayList<String> child;
        IntercityOrderEntity orderEntity = null;
        if (forHistory){
            orderEntity = OrderConvertor.INSTANCE.convertToHistory(orderHistoryRepository.findById(idOrder).orElse(null));
        }else{
            orderEntity = orderRepository.findById(idOrder).orElse(null);
        }
        IcOrderCancelHistoryEntity och = orderCancelHistoryRepository.findById(idOrder).orElse(null);
        for (IcDetailVO.StatusHistory v:statusHistories) {
            child = new ArrayList<>();
            switch (v.getStatus()){
                case 0://乘客发单
                    v.setTitle("乘客发单");
                    child.add(StrUtil.join(":","发单时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","预估里程/时长",StrUtil.builder().append(orderEntity.getReferenceDistance()).append("公里/").append(orderEntity.getEstimatedTime()).append("分钟")));
                    child.add(StrUtil.join(":","预估价格","￥"+orderEntity.getEstimatedMoney()));
                    statusHistoriesR.add(v);
                    break;
//                case 1://平台派单
//                    v.setTitle("平台派单");
//                    child.add(StrUtil.join(":","车牌号",StrUtil.builder().append(orderEntity.getPlateNumber())));
//                    child.add(StrUtil.join(":","车辆",StrUtil.builder().append(orderEntity.getModel())));
//                    child.add(StrUtil.join(":","预估接驾",StrUtil.builder().append("待定")));
//                    statusHistoriesR.add(v);
//                    break;
                case 2://司机接单
                    if (orderEntity.getIdDriver()!=null){
                        v.setTitle("司机接单");
                        VehicleEntity dv = vehicleRepository.findByIdDriver(orderEntity.getIdDriver());
                        child.add(StrUtil.join(":","接单时间",v.getCreateTime()));
                        child.add(StrUtil.join(":","车牌号",StrUtil.builder().append(dv.getPlateNumber())));
                        //child.add(StrUtil.join(":","车辆",StrUtil.builder().append(orderEntity.getModel())));
                        child.add(StrUtil.join(":","预估接驾里程/时长",StrUtil.builder().append("待定")));
                        statusHistoriesR.add(v);
                    }

                    break;
                case 4://司机到达上车点
                    v.setTitle("司机到达上车点");
                    child.add(StrUtil.join(":","到达上车地点时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","真实接驾里程/时长",StrUtil.builder().append("待定")));
                    statusHistoriesR.add(v);
                    break;
                case 5://乘客上车
                    v.setTitle("乘客上车");
                    child.add(StrUtil.join(":","上车时间",v.getCreateTime()));
                    statusHistoriesR.add(v);
                    break;
                case 6://到达目的地
                    v.setTitle("到达目的地");
                    child.add(StrUtil.join(":","到达时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","实际里程",orderEntity.getOrderDistance()));
                    statusHistoriesR.add(v);
                    break;
                case 7://未支付
                    v.setTitle("订单待支付");
                    child.add(StrUtil.join(":","支付状态",StrUtil.builder().append("未支付")));
                    child.add(StrUtil.join(":","支付时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","乘客应付",orderEntity.getPayMoney()));
                    child.add(StrUtil.join(":","司机应收",orderEntity.getOrderMoney()));
                    statusHistoriesR.add(v);
                    break;
                case 8://已支付
                    v.setTitle("订单支付");
                    child.add(StrUtil.join(":","支付状态",StrUtil.builder().append("已支付")));
                    child.add(StrUtil.join(":","支付时间",v.getCreateTime()));
                    child.add(StrUtil.join(":","乘客应付",orderEntity.getPayMoney()));
                    child.add(StrUtil.join(":","司机应收",orderEntity.getOrderMoney()));
                    statusHistoriesR.add(v);
                    break;
                case 11://乘客下单后取消订单 用户取消、取消原因、操作时间
                    v.setTitle("已取消");
                    child.add("用户取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
//                case 12://司机已拒绝
//                    v.setTitle("司机已拒绝");
//                    child.add(StrUtil.join(":","真实接驾",StrUtil.builder().append("待定")));
//                    statusHistoriesR.add(v);
//                    break;
                case 13://系统已销单
                    v.setTitle("已取消");
                    child.add("系统取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
                case 14://司机已取消
                    v.setTitle("已取消");
                    child.add("司机取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
                case 15://客服已取消
                    v.setTitle("已取消");
                    child.add("客服取消");
                    if(och!=null){
                        child.add(StrUtil.join(":","取消原因",och.getReason()));
                        child.add(StrUtil.join(":","操作时间",och.getCreateTime()));
                    }
                    statusHistoriesR.add(v);
                    break;
            }
            v.setChild(child);
        }
        return new IcDetailVO(base, statusHistoriesR,null);
    }

    /**
     * 城际任务详情
     * @param idTask
     * @return
     */
    @Override
    public IcTaskDetailVO icTaskDetail(String idTask) {
        IcTaskDetailVO taskDetailVO = orderMapper.icTaskDetail(idTask);
        if (taskDetailVO != null) {
            taskDetailVO.setOrders(orderMapper.searchOrderWithTaskID(idTask));
        } else {
            throw new BusinessException(5002, "未取到任务["+idTask+"]的信息资料，请联系系统管理员！");
        }
        return taskDetailVO;
    }

    /**
     * 城际历史任务详情
     * @param idTask
     * @return
     */
    @Override
    public IcTaskDetailVO icTaskHistoryDetail(String idTask) {
        IcTaskDetailVO taskDetailVO = orderMapper.icTaskHistoryDetail(idTask);
        if (taskDetailVO != null) {
            taskDetailVO.setOrders(orderMapper.searchOrderWithTaskID(idTask));
        } else {
            throw new BusinessException(5002, "未取到任务["+idTask+"]的信息资料，请联系系统管理员！");
        }
        return taskDetailVO;
    }

    /**
     * 查询运营商上线线路
     * @param idFranchisee
     * @return
     */
    @Override
    public List<IntercityLineEntity> getIcLineByIdFranchisee(String idFranchisee) {
        return lineRepository.findByIdFranchiseeAndOnlineStatus(idFranchisee,1);
    }

    @Override
    public Boolean icOrderDestroy(IcOrderDestroyParam param) {
        IntercityOrderEntity intercityOrderEntity;
        try {
            intercityOrderEntity = orderRepository.findById(param.getIdOrder()).get();
            if (intercityOrderEntity.getStatus()==Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED)
                throw new BusinessException(5002,"该订单已被销单,无法重复销单");
        }catch (NoSuchElementException e){
            throw new BusinessException(5002,"订单ID[idOrder]不存在,请检查");
        }
        intercityOrderEntity.setStatus(Constants.OrderStatus.ORDER_STATUS_ADMIN_CANCELED);
        orderRepository.save(intercityOrderEntity);
        return destroyRepository.save(ExpressConvertor.INSTANCE.convert(param))!=null;
    }

    @Override
    public Boolean icReMemo(String idOrder, String memo) {
        return orderMapper.icReMemo(idOrder,memo);
    }


    /**
     * 订单支付详情
     * @param idOrder
     * @return
     */
    @Override
    public IcOrderBillInfoVO getOrderBillInfo(String idOrder,Boolean forHistory) {

        IntercityOrderEntity order = null;
        if (forHistory){
            order = OrderConvertor.INSTANCE.convertToHistory(orderHistoryRepository.findById(idOrder).orElse(null));
        }else{
            order = orderRepository.findById(idOrder).orElse(null);
        }
        if (order==null)throw new BusinessException(5002,"订单号不存在请检查");

        IntercityOrderSettlementEntity es = orderSettlementRepository.findByIdOrder(idOrder);
        IcDriverAccountDetailEntity ed = accountDetailRepository.findByRelateOrderNo(idOrder);

        if (es == null)
            es = new IntercityOrderSettlementEntity();
        if (ed == null)
            ed = new IcDriverAccountDetailEntity();

        IcOrderBillInfoVO.PassengerBill pb = new IcOrderBillInfoVO.PassengerBill();
        /** 总价 */
        pb.setTotal(es.getOrderTotal());
        /** 时长费 */
        pb.setDuration(0F);
        /** 里程费 */
        pb.setMileage(0F);
        /** 远途费 */
        pb.setLongDistance(es.getOrderLongDistanceMoney());
        IcOrderBillInfoVO.PassengerPayInfo pp = new IcOrderBillInfoVO.PassengerPayInfo();
        /** 支付金额 */
        pp.setPayMoney(order.getPayMoney());
        /** 支付时间 */
        if (es.getPayTime()!=null){
            pp.setPayTime(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(es.getPayTime()));
        }
        /** 支付状态 */
        pp.setPayStatus(Constants.Payment_Status.get(order.getPaymentStatus()));
        /** 支付渠道 */
        pp.setPayChannel(Constants.Payment_Type.get(es.getPaymentType()));
        /** 发票状态 */
        pp.setInvoiceStatus("-");
        /** 退款费用 */
        pp.setRefund(0F);
        /** 高速费 */
        pp.setHighSpeed(0F);
        /** 停车费 */
        pp.setParking(0F);
        /** 路桥费 */
        pp.setBridge(es.getOrderRoadMoney());
        /** 限时折扣 */
        pp.setDiscount(0F);
        /** 其他费 */
        pp.setOther(es.getOrderOther());
        /** 节假日服务费 */
        pp.setHoliday(0F);

        IcOrderBillInfoVO.DriverBill db = new IcOrderBillInfoVO.DriverBill();
        /** 总价 */
        if (ed != null){
            db.setTotal(ed.getMoney());
        }else{
            db.setTotal(0F);
        }
        /** 基础费 */
        db.setBasic(0F);
        /** 时长费 */
        db.setDuration(0F);
        /** 里程费 */
        db.setMileage(0F);
        /** 高速费 */
        db.setHighSpeed(0F);
        /** 停车费 */
        db.setParking(0F);
        /** 路桥费 */
        db.setBridge(0F);
        /** 远途费 */
        db.setLongDistance(0F);
        /** 其他费 */
        db.setOther(0F);
        /** 免佣补贴金额 */
        db.setAllowance(0F);
        /** 节假日服务费 */
        db.setHoliday(0F);
        /** 信息服务费 */
        db.setInformation(0F);

        return new IcOrderBillInfoVO(pb, pp,db);
    }

    /**
     * 订单支付详情
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<IcOrderSettlementViewVO> icOrderBillViewLst(IcSettlementViewListParam param) {
        Page<IcOrderSettlementViewVO> page = orderSettlementRepository.findByIdFranchisee(param.getIdFranchisee(), PageRequest.of(param.getPageIndex() - 1, param.getPageSize()));
        return new PagingResultVO<>(page.getTotalElements(),page.getContent());
    }

    @Override
    public IcOrderInfoVO orderInfo(String idOrder) {
        IntercityOrderEntity entity = orderRepository.findById(idOrder).get();
        if (entity == null)
            throw new BusinessException(5002,"订单号不存在请检查");
        return IntercityConvertor.INSTANCE.convert(entity);
    }

    @Override
    public IntercityLineEntity findIdLineByStartCityCodeAndEndCityCode(String startCityCode,String endCityCode) {
        IntercityLineEntity entity = lineRepository.findByStartCityCodeAndEndCityCode(startCityCode,endCityCode);
        if (entity == null)
            return null;
        return entity;
    }

    public OrderPriceVO calIntercityPrice(IntercityPriceParam param) {
        RouteVO routeVO = routeRedis.calOrderDistance(
                param.getCoordinateType()
                , param.getOrigins(), param.getDestinations());

        if (routeVO == null)
            return null;

        param.setOrderDistance(routeVO.getDistance());
        param.setSpendTime(routeVO.getSpendTime());

        boolean stp = false;
        ApplyStationEntity entity = null;
        if (StringUtil.isNotBlank(param.getIdStation()))
        {
            entity = applyStationRepository.findByIdStation(param.getIdStation());
            if (entity == null) {
                throw new BusinessException(5002, "站点业务未开通，请核查是否开通业务");
            } else {
                if (entity != null && param.getInStation() == 0) {
                    if (param.getInStation() == Constants.StationType.PICKUP) {
                        stp = (entity.getSendStationType() == 0);
                    } else if (param.getInStation() == Constants.StationType.SENDING) {
                        stp = (entity.getPickStationType() == 0);
                    }
                }
            }
        }

        OrderPriceVO orderPrice = null;
        if (stp) {
            orderPrice = icStpCalculate(param);
        } else {
            orderPrice = icCalculate(param);
        }

        return orderPrice;
    }

    /**
     * 城际站点接驳
     * @param param
     * @return
     */
    private OrderPriceVO icCalculate(IntercityPriceParam param) {
        //DistanceMatrixVO rm = weMapTemplate.matrix().matrixDriving(param.getOrigins(), param.getDestinations());

        IntercityPriceEntity icp = icPriceRepository.findByIdLine(param.getIdLine());
        if (ObjectUtil.isEmpty(icp))
            throw new BusinessException(5002, "当前线路[idLine:"+param.getIdLine()+"]未设置价格请联系管理员！");
        OrderPriceVO orderPrice = new OrderPriceVO();
        // 计算价格
        // 普通服务起步价
        float money = 0.0f;
        float basePrice = icp.getServicePrice().floatValue();
        BigDecimal dx1 = BigDecimal.valueOf(0.00);
        BigDecimal dt1 = BigDecimal.valueOf(0.00);
        float orderDistance = param.getOrderDistance();
        if (orderDistance > icp.getMaxServiceMileage()) {
            BigDecimal distance = BigDecimal.valueOf(orderDistance - icp.getMaxServiceMileage());
            dx1 = NumberUtil.toBigDecimal(icp.getExceedingMileagePrice()).multiply(distance);
        }
        if(icp.getWaitingTimePrice() != null){
            if (param.getSpendTime() > icp.getMaxWaitingTime()) { //TODO 等待时间未定
                BigDecimal time = BigDecimal.valueOf(param.getSpendTime() - icp.getMaxWaitingTime());
                dt1 = NumberUtil.toBigDecimal(icp.getWaitingTimePrice()).multiply(time);
            }
        }
        if (param.getCarpoolType() !=null && param.getCarpoolType()==Constants.OrderCarpoolType.Chartered){
            basePrice = icp.getCharteredCarPrice().floatValue();
        }else {
            basePrice = basePrice*param.getPassengerNumber();
        }

        float otherPrice = dx1.floatValue() + dt1.floatValue();
        money = basePrice + otherPrice;
        //
        orderPrice.setOrderDistance(orderDistance);
        orderPrice.setSpendTime(param.getSpendTime());
        orderPrice.setIdServicePriceType(String.valueOf(icp.getIdIntercityLinePrice()));
        orderPrice.setTotalPrice(Convert.toFloat(new BigDecimal(money).setScale(2, RoundingMode.HALF_UP).toString()));
        orderPrice.setBasePrice(Convert.toFloat(new BigDecimal(basePrice).setScale(2, RoundingMode.HALF_UP).toString()));

        return orderPrice;
    }

    /**
     * 城际站点接驳
     * @param espParam
     * @return
     */
    private OrderPriceVO icStpCalculate(IntercityPriceParam espParam) {
        float money = 0;
        float basePrice = 0;
        float otherPrice = 0;

        List<IntercityStpPriceEntity> lst = icStpPriceRepository.findByIdCityLineAndIdStation(espParam.getIdCityLine(), espParam.getIdStation());
        if (lst == null || (lst != null && lst.size() == 0))
            lst = icStpPriceRepository.findByIdLineAndIdStation(espParam.getIdLine(), espParam.getIdStation());
        IntercityStpPriceEntity stp = null;

        //寻找对应站点定价，没有找到则采用当前城市定价
        if (lst != null) {
            for(int i=0; i<lst.size(); i++) {
                IntercityStpPriceEntity stpIndex = lst.get(i);
                if (Constants.OrderCarpoolType.Chartered == espParam.getCarpoolType()) {
                    if (Constants.OrderCarpoolType.Chartered == stpIndex.getCarpoolType()) {
                        if (espParam.getIdVehicleType() == stpIndex.getIdVehicleType()) {
                            if (StringUtil.isBlank(stpIndex.getIdStation())) {
                                stp = lst.get(i);
                                if (StringUtil.isBlank(espParam.getIdStation()))
                                    break;
                            } else if (StringUtil.isNotBlank(espParam.getIdStation()) && espParam.getIdStation().equals(stpIndex.getIdStation())) {
                                stp = lst.get(i);
                                break;
                            }
                        }
                    }
                } else {
                    if (Constants.OrderCarpoolType.Carpool == stpIndex.getCarpoolType()) {
                        if (StringUtil.isBlank(stpIndex.getIdStation())) {
                            stp = lst.get(i);
                            if (StringUtil.isBlank(espParam.getIdStation()))
                                break;
                        } else if (StringUtil.isNotBlank(espParam.getIdStation()) && espParam.getIdStation().equals(stpIndex.getIdStation())) {
                            stp = lst.get(i);
                            break;
                        }
                    }
                }
            }
        }

        if (stp != null) {
            float od = espParam.getOrderDistance();
            if (od > stp.getLongDistanceKilometers()) {
                float ltp = od - stp.getLongDistanceKilometers();
                basePrice = stp.getLongDistanceFee();
                otherPrice = ltp * stp.getOverMileageFee();
            } else if (od > stp.getBaseKilometers()) {
                basePrice = stp.getLongDistanceFee();
            } else if (od > stp.getStartingKilometers()) {
                basePrice = stp.getBaseFee();
            } else {
                basePrice = stp.getStartingFee();
            }
        } else {
            return null;
        }

        if (espParam.getCarpoolType() != null && espParam.getCarpoolType() == Constants.OrderCarpoolType.Carpool) {
            money = basePrice + otherPrice;
        } else {
            basePrice = basePrice*espParam.getPassengerNumber();
            money = basePrice + otherPrice;
        }

        OrderPriceVO opv = new OrderPriceVO();
        opv.setIdServicePriceType(stp.getIdServicePriceType());
        opv.setTotalPrice(Convert.toFloat(new BigDecimal(money).setScale(2, RoundingMode.HALF_UP).toString()));
        opv.setBasePrice(Convert.toFloat(new BigDecimal(basePrice).setScale(2, RoundingMode.HALF_UP).toString()));
        opv.setOtherPrice(Convert.toFloat(new BigDecimal(otherPrice).setScale(2, RoundingMode.HALF_UP).toString()));
        opv.setOrderDistance(espParam.getOrderDistance());
        opv.setSpendTime(espParam.getSpendTime());
        opv.setPerKilometres(stp.getLongDistanceFee());
        opv.setPerTime(0);
        opv.setOverMileMoney(stp.getOverMileageFee());
        opv.setOverTimeMoney(stp.getDurationFee());

        return opv;
    }

}
